﻿using System.Collections.Generic;

namespace XUBadWord
{
    public class XUBadWordMgr
    {
        private static XUBadWordMgr instance;
        public static XUBadWordMgr GetInstance()
        {
            if (instance == null)
            {
                instance = new XUBadWordMgr();
            }
            return instance;
        }

        /// <summary>
        /// 使用双向图结构存储
        /// </summary>
        private Dictionary<char, Dictionary<string, int>> nodeMap = new Dictionary<char, Dictionary<string, int>>();

        /// <summary>
        /// 添加非法词
        /// </summary>
        /// <param name="word">非法词</param>
        public void AddWord(string word)
        {
            if (string.IsNullOrEmpty(word))
            {
                return;
            }

            char valuePre = char.MinValue;
            foreach (char value in word)
            {
                if (!nodeMap.ContainsKey(value))
                {
                    nodeMap.Add(value, new Dictionary<string, int>());
                }
                if (valuePre != char.MinValue)
                {
                    nodeMap[valuePre][value.ToString()] = 1;
                }
                valuePre = value;
            }
            nodeMap[valuePre][word] = 0;
        }

        public bool HasBadWord(string content)
        {
            int length = content.Length;
            for (int head = 0; head < length; head++)
            {
                int index = head;

                char value;
                string word = "";
                Dictionary<string, int> node;

                value = content[index];
                word = string.Format("{0}{1}", word, value);
                nodeMap.TryGetValue(value, out node);
                while (node != null)
                {
                    if (node.ContainsKey(word) && node[word] == 0)
                    {
                        return true;
                    }
                    index++;
                    if (length <= index)
                    {
                        break;
                    }
                    value = content[index];
                    word = string.Format("{0}{1}", word, value);
                    nodeMap.TryGetValue(value, out node);
                }
            }
            return false;
        }

        public string ReplaceBadWord(string content)
        {
            List<char> charTbl = new List<char>();
            foreach (var value in content)
            {
                charTbl.Add(value);
            }

            int length = content.Length;
            for (int head = 0; head < length; head++)
            {
                int index = head;

                char value;
                string word = "";
                Dictionary<string, int> node;

                value = content[index];
                word = string.Format("{0}{1}", word, value);
                nodeMap.TryGetValue(value, out node);
                while (node != null)
                {
                    if (node.ContainsKey(word) && node[word] == 0)
                    {
                        for (int i = head; i <= index; i++)
                        {
                            charTbl[i] = '*';
                        }
                        head = index;
                    }
                    index++;
                    if (length <= index)
                    {
                        break;
                    }
                    value = content[index];
                    word = string.Format("{0}{1}", word, value);
                    nodeMap.TryGetValue(value, out node);
                }
            }

            return string.Join("", charTbl);
        }
    }
}
